/**
* @file image_processor_v300.cpp
*
* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "image_processor_v300.h"

#include "common/log_inner.h"
#include "error_codes_inner.h"
#include "aicpu/dvpp/dvpp_def.h"
#include "single_op/dvpp/common/dvpp_util.h"
#include "hi_dvpp_for_acl_internal.h"

namespace {
    constexpr uint32_t MAX_PIC_HEIGHT = 4096U;
    constexpr uint32_t MAX_PIC_WIDTH = 4096U;
    constexpr uint32_t JPEGE_DEFAULT_HEIGHT = 8192U;
    constexpr uint32_t JPEGE_DEFAULT_WIDTH = 8192;
    constexpr uint32_t DEFAULT_FILTER_LEVEL = 1U;
    constexpr uint16_t DEFAULT_DIVISOR = 256U;
    constexpr uint32_t YUV_SCALER_MODE = 5U;
    using DestroyChannelFunc = hi_s32 (*)(hi_s32);
    const std::map<acldvppChannelMode, DestroyChannelFunc> destroyChnMap = {
        {DVPP_CHNMODE_JPEGD, &hi_mpi_jpegd_destroy_chn_for_acl},
        {DVPP_CHNMODE_JPEGE, &hi_mpi_jpege_destroy_chn_for_acl},
        {DVPP_CHNMODE_VPC, &hi_mpi_vpc_destroy_chn_for_acl}
    };
    std::vector<uint32_t> interpolationVec {BILINEAR_FOR_ACL, BILINEAR_FOR_ACL, NEAREST_FOR_ACL,
        BILINEAR_FOR_ACL, NEAREST_FOR_ACL, YUV_SCALER_MODE};

    void VpcAlign(const acldvppPixelFormat format, hi_vpc_pic_info &vpcPicDesc)
    {
        switch (format) {
            case PIXEL_FORMAT_YUV_SEMIPLANAR_420:
            case PIXEL_FORMAT_YVU_SEMIPLANAR_420:
                // width and height should be even
                vpcPicDesc.picture_width -= (vpcPicDesc.picture_width & 1U);
                vpcPicDesc.picture_height -= (vpcPicDesc.picture_height & 1U);
                break;
            case PIXEL_FORMAT_YUV_SEMIPLANAR_440:
            case PIXEL_FORMAT_YVU_SEMIPLANAR_440:
                vpcPicDesc.picture_height -= (vpcPicDesc.picture_height & 1U);
                break;
            case PIXEL_FORMAT_YUV_SEMIPLANAR_422:
            case PIXEL_FORMAT_YVU_SEMIPLANAR_422:
            case PIXEL_FORMAT_YUYV_PACKED_422:
            case PIXEL_FORMAT_UYVY_PACKED_422:
            case PIXEL_FORMAT_YVYU_PACKED_422:
            case PIXEL_FORMAT_VYUY_PACKED_422:
                vpcPicDesc.picture_width -= (vpcPicDesc.picture_width & 1U);
                break;
            default:
                break;
        }
    }

    void ConvertUserPicDescToHimpiVpcPicInfo(const aicpu::dvpp::DvppPicDesc &dvppPicDesc,
        const bool isVpcInput, hi_vpc_pic_info &vpcPicDesc)
    {
        vpcPicDesc.picture_address = reinterpret_cast<void *>(dvppPicDesc.data);
        vpcPicDesc.picture_buffer_size = dvppPicDesc.size;
        vpcPicDesc.picture_width = dvppPicDesc.width;
        vpcPicDesc.picture_height = dvppPicDesc.height;
        vpcPicDesc.picture_width_stride = dvppPicDesc.widthStride;
        vpcPicDesc.picture_height_stride = dvppPicDesc.heightStride;
        vpcPicDesc.picture_format = static_cast<hi_pixel_format>(dvppPicDesc.format);
        if (isVpcInput) {
            VpcAlign(static_cast<acldvppPixelFormat>(dvppPicDesc.format), vpcPicDesc);
        }
        ACL_LOG_DEBUG("picture size %u, width %u, height %u, widthstride %u, height stride %u, format %d",
            dvppPicDesc.size, dvppPicDesc.width, dvppPicDesc.height, dvppPicDesc.widthStride, dvppPicDesc.heightStride,
            dvppPicDesc.format);
    }

    void ConvertUserPicDescToHimpiPicInfo(const aicpu::dvpp::DvppPicDesc &dvppPicDesc, hi_pic_info &picDesc)
    {
        picDesc.picture_address = reinterpret_cast<void *>(dvppPicDesc.data);
        picDesc.picture_buffer_size = dvppPicDesc.size;
        picDesc.picture_width = dvppPicDesc.width;
        picDesc.picture_height = dvppPicDesc.height;
        picDesc.picture_width_stride = dvppPicDesc.widthStride;
        picDesc.picture_height_stride = dvppPicDesc.heightStride;
        picDesc.picture_format = static_cast<hi_pixel_format>(dvppPicDesc.format);
        ACL_LOG_DEBUG("picture size %u, width %u, height %u, widthstride %u, height stride %u, format %d",
            dvppPicDesc.size, dvppPicDesc.width, dvppPicDesc.height, dvppPicDesc.widthStride, dvppPicDesc.heightStride,
            dvppPicDesc.format);
    }

    void RefreshHimpiPicInfoToUserPicDesc(const hi_pic_info &picDesc, aicpu::dvpp::DvppPicDesc &dvppPicDesc)
    {
        dvppPicDesc.size = picDesc.picture_buffer_size;
        dvppPicDesc.width = picDesc.picture_width;
        dvppPicDesc.height = picDesc.picture_height;
        dvppPicDesc.widthStride = picDesc.picture_width_stride;
        dvppPicDesc.heightStride = picDesc.picture_height_stride;
        dvppPicDesc.format = picDesc.picture_format;
    }

    aclError ConvertUserResizeCfgToHimpiResizeInfo(const aicpu::dvpp::DvppPicDesc &dvppPicDesc,
        const acldvppResizeConfig *const resizeConfig, hi_vpc_resize_info &resizeInfo,
        const acldvppBorderConfig *const borderConfig,
        const acldvppRoiConfig *const pasteArea)
    {
        resizeInfo.resize_width = dvppPicDesc.width;
        resizeInfo.resize_height = dvppPicDesc.height;
        resizeInfo.interpolation = 0U; // default mode
        if (pasteArea != nullptr) {
            ACL_CHECK_UINT32_GREATER(pasteArea->dvppRoiConfig.rightOffset, pasteArea->dvppRoiConfig.leftOffset);
            resizeInfo.resize_width = static_cast<uint32_t>(pasteArea->dvppRoiConfig.rightOffset -
                pasteArea->dvppRoiConfig.leftOffset + 1U);
            ACL_CHECK_UINT32_GREATER(pasteArea->dvppRoiConfig.downOffset, pasteArea->dvppRoiConfig.upOffset);
            resizeInfo.resize_height = static_cast<uint32_t>(pasteArea->dvppRoiConfig.downOffset -
                pasteArea->dvppRoiConfig.upOffset + 1U);
        }
        if (borderConfig != nullptr) {
            const uint32_t borderWidthLength = (static_cast<uint32_t>(borderConfig->dvppBorderConfig.left) +
                static_cast<uint32_t>(borderConfig->dvppBorderConfig.right));
            ACL_CHECK_UINT32_GREATER(dvppPicDesc.width, borderWidthLength);
            resizeInfo.resize_width = dvppPicDesc.width - borderWidthLength;
            const uint32_t borderHeightLength = (static_cast<uint32_t>(borderConfig->dvppBorderConfig.top) +
                static_cast<uint32_t>(borderConfig->dvppBorderConfig.bottom));
            ACL_CHECK_UINT32_GREATER(dvppPicDesc.height, borderHeightLength);
            resizeInfo.resize_height = dvppPicDesc.height - borderHeightLength;
        }
        if (resizeConfig != nullptr) {
            resizeInfo.interpolation = interpolationVec[resizeConfig->dvppResizeConfig.interpolation];
        }
        ACL_LOG_INFO("set resize width %u, height %u, interpolation is %u",
            resizeInfo.resize_width, resizeInfo.resize_height, resizeInfo.interpolation);
        return ACL_SUCCESS;
    }

    aclError ConvertUserRoiCfgToHimpiCropInfo(const acldvppRoiConfig *const cropArea, hi_vpc_crop_region &cropRegion)
    {
        cropRegion.top_offset = static_cast<uint32_t>(cropArea->dvppRoiConfig.upOffset);
        cropRegion.left_offset = static_cast<uint32_t>(cropArea->dvppRoiConfig.leftOffset);
        ACL_CHECK_UINT32_GREATER(cropArea->dvppRoiConfig.rightOffset, cropArea->dvppRoiConfig.leftOffset);
        cropRegion.crop_width = static_cast<uint32_t>(cropArea->dvppRoiConfig.rightOffset -
            cropArea->dvppRoiConfig.leftOffset) + 1U;
        ACL_CHECK_UINT32_GREATER(cropArea->dvppRoiConfig.downOffset, cropArea->dvppRoiConfig.upOffset);
        cropRegion.crop_height = static_cast<uint32_t>(cropArea->dvppRoiConfig.downOffset -
            cropArea->dvppRoiConfig.upOffset) + 1U;
        return ACL_SUCCESS;
    }

    void ConvertUserBorderCfgToHimpiBorderInfo(const acldvppBorderConfig *const borderConfig,
        hi_vpc_make_border_info &makeBorderInfo)
    {
        const aicpu::dvpp::DvppBorderConfig &borderCfg = borderConfig->dvppBorderConfig;
        makeBorderInfo.top = static_cast<uint32_t>(borderCfg.top);
        makeBorderInfo.bottom = static_cast<uint32_t>(borderCfg.bottom);
        makeBorderInfo.left = static_cast<uint32_t>(borderCfg.left);
        makeBorderInfo.right = static_cast<uint32_t>(borderCfg.right);
        makeBorderInfo.border_type = static_cast<hi_vpc_bord_type>(borderCfg.borderType);
        for (uint32_t i = 0U; i < acl::DVPP_MAKE_BORDER_MAX_COMPONENT; ++i) {
            makeBorderInfo.scalar_value.val[i] = borderCfg.value[i];
        }
    }

    aclError SetCscMatrixConfig(const acldvppChannelDesc *const channelDesc, const hi_s32 chn)
    {
        std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
        const std::unique_lock<std::mutex> lk{mutexMap};
        const auto &it = channelDesc->tlvParamMap.find(acl::DVPP_CSC_MATRIX);
        if (it != channelDesc->tlvParamMap.end()) {
            const uint32_t cscMatrix =
                static_cast<aicpu::dvpp::DvppCscMatrixConfig *>(it->second.value.get())->cscMatrix;
            ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_sys_set_chn_csc_matrix(HI_ID_VPC,
                chn, static_cast<hi_csc_matrix>(cscMatrix), nullptr), hi_mpi_sys_set_chn_csc_matrix);
        }
        return ACL_SUCCESS;
    }

    aclError SetJpegdPrecisionModeConfig(const acldvppChannelDesc *const channelDesc, const hi_s32 chn)
    {
        std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
        const std::unique_lock<std::mutex> lk{mutexMap};
        uint32_t precisionMode = static_cast<uint32_t>(ACL_YUVOUT_ALIGN_DOWN_COMPAT);
        const auto &it = channelDesc->tlvParamMap.find(acl::DVPP_PRECISION_MODE_JPEGE);
        if (it != channelDesc->tlvParamMap.end()) {
            precisionMode =
                static_cast<aicpu::dvpp::DvppJpegdPrecisionModeConfig *>(it->second.value.get())->precisionMode;
        }
        ACL_LOG_INFO("in SetJpegdPrecisionModeConfig, precisionMode = %u", static_cast<uint32_t>(precisionMode));
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_vdec_set_jpegd_precision_mode(chn,
            static_cast<hi_jpegd_precision_mode>(precisionMode)), hi_mpi_vdec_set_jpegd_precision_mode);
        return ACL_SUCCESS;
    }

    void GetJpegeConfig(const acldvppChannelDesc *const channelDesc, hi_venc_chn_attr &jpegeAttr)
    {
        jpegeAttr.venc_attr.type = HI_PT_JPEG;
        uint32_t height = JPEGE_DEFAULT_HEIGHT;
        uint32_t width = JPEGE_DEFAULT_WIDTH;
        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> lk{mutexMap};
            auto it = channelDesc->tlvParamMap.find(acl::DVPP_HEIGHT_JPEGE);
            if (it != channelDesc->tlvParamMap.end()) {
                height = static_cast<aicpu::dvpp::DvppChannelHeightConfig *>(it->second.value.get())->height;
            }
            it = channelDesc->tlvParamMap.find(acl::DVPP_WIDTH_JPEGE);
            if (it != channelDesc->tlvParamMap.end()) {
                width = static_cast<aicpu::dvpp::DvppChannelWidthConfig *>(it->second.value.get())->width;
            }
        }
        jpegeAttr.venc_attr.pic_height = height;
        jpegeAttr.venc_attr.max_pic_height = height;
        jpegeAttr.venc_attr.pic_width = width;
        jpegeAttr.venc_attr.max_pic_width = width;
    }

    aclError GetHimpiChannel(const acldvppChannelDesc *const channelDesc,
        const acldvppChannelMode &mode, int32_t &chn)
    {
        std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForHimpiChnMap);
        const std::unique_lock<std::mutex> lk{mutexMap};
        const auto it = channelDesc->himpiChannelIdMap.find(mode);
        if (it == channelDesc->himpiChannelIdMap.end()) {
            ACL_LOG_ERROR("channel %d is not created, please use acldvppCreateChannel first", mode);
            return ACL_ERROR_FAILURE;
        }
        chn = it->second;
        return ACL_SUCCESS;
    }

    aclError CheckSrcBatchSize(const acldvppBatchPicDesc *const srcBatchPicDescs, const uint32_t size)
    {
        const bool validParam = (size == 0U) || (srcBatchPicDescs->dvppBatchPicDescs.batchSize < size);
        if (validParam) {
            ACL_LOG_ERROR("[Check][BatchSize]srcBatchPicDescs batchSize less than roiNums size or size = 0, "
                "batch size = %u, size = %u.", srcBatchPicDescs->dvppBatchPicDescs.batchSize, size);
            const std::string convertedStr = std::to_string(srcBatchPicDescs->dvppBatchPicDescs.batchSize);
            const std::string errMsg =
                acl::AclErrorLogManager::FormatStr("less than roiNums size[%u] or size = 0", size);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"srcBatchPicDescs batchSize", convertedStr.c_str(), errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        return ACL_SUCCESS;
    }

    aclError CheckDstBatchSize(const acldvppBatchPicDesc *const dstBatchPicDescs, const uint32_t totalRoiNums)
    {
        if (dstBatchPicDescs->dvppBatchPicDescs.batchSize < totalRoiNums) {
            ACL_LOG_ERROR("[Check][BatchSize]dstBatchPicDescs batchSize less than total size, "
                "batch size = %u, size = %u.", dstBatchPicDescs->dvppBatchPicDescs.batchSize, totalRoiNums);
            const std::string convertedStr = std::to_string(dstBatchPicDescs->dvppBatchPicDescs.batchSize);
            const std::string errMsg =
                acl::AclErrorLogManager::FormatStr("less than totalRoiNums size[%u]", totalRoiNums);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"dstBatchPicDescs batchSize", convertedStr.c_str(), errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        return ACL_SUCCESS;
    }

    void FillVideoFrameInfo(acldvppPicDesc *const inputDesc, hi_video_frame_info &frame)
    {
        frame.v_frame.width = inputDesc->dvppPicDesc.width;
        frame.v_frame.height = inputDesc->dvppPicDesc.height;
        frame.v_frame.pixel_format = static_cast<hi_pixel_format>(inputDesc->dvppPicDesc.format);
        frame.v_frame.field = HI_VIDEO_FIELD_FRAME;
        frame.v_frame.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
        frame.v_frame.compress_mode = HI_COMPRESS_MODE_NONE;
        frame.v_frame.video_format = HI_VIDEO_FORMAT_LINEAR;
        frame.v_frame.color_gamut = HI_COLOR_GAMUT_BT709;

        frame.v_frame.width_stride[0] = inputDesc->dvppPicDesc.widthStride;
        frame.v_frame.width_stride[1] = inputDesc->dvppPicDesc.widthStride;
        frame.v_frame.width_stride[2] = inputDesc->dvppPicDesc.widthStride;

        frame.v_frame.header_virt_addr[0] = reinterpret_cast<void *>(inputDesc->dvppPicDesc.data);
        frame.v_frame.header_virt_addr[1] = reinterpret_cast<void *>(inputDesc->dvppPicDesc.data);
        frame.v_frame.header_virt_addr[2] = reinterpret_cast<void *>(inputDesc->dvppPicDesc.data);

        frame.v_frame.virt_addr[0] = reinterpret_cast<void *>(inputDesc->dvppPicDesc.data);
        frame.v_frame.virt_addr[1] = reinterpret_cast<void *>(inputDesc->dvppPicDesc.data +
            static_cast<size_t>(inputDesc->dvppPicDesc.widthStride * inputDesc->dvppPicDesc.heightStride));
        frame.v_frame.virt_addr[2] = frame.v_frame.virt_addr[1];
    }

    void ConvertJpegFormat(const hi_jpeg_raw_format himpiJpegFormat, acldvppJpegFormat *const format)
    {
        static std::map<hi_jpeg_raw_format, acldvppJpegFormat> himpiAcpJpegFormatMap = {
            {HI_JPEG_RAW_FORMAT_YUV444, ACL_JPEG_CSS_444},
            {HI_JPEG_RAW_FORMAT_YUV422, ACL_JPEG_CSS_422},
            {HI_JPEG_RAW_FORMAT_YUV420, ACL_JPEG_CSS_420},
            {HI_JPEG_RAW_FORMAT_YUV440, ACL_JPEG_CSS_440},
            {HI_JPEG_RAW_FORMAT_YUV400, ACL_JPEG_CSS_GRAY},
            {HI_JPEG_RAW_FORMAT_YUV411, ACL_JPEG_CSS_411},
            {HI_JPEG_RAW_FORMAT_MAX, ACL_JPEG_CSS_UNKNOWN}
        };
        const auto it = himpiAcpJpegFormatMap.find(himpiJpegFormat);
        if (it != himpiAcpJpegFormatMap.end()) {
            *format = it->second;
        }
    }

    aclError CreateHimpiChannelDvppVpc(const acldvppChannelDesc *const channelDesc, hi_s32 &chn)
    {
        hi_vpc_chn_attr attr = {};
        attr.pic_height = MAX_PIC_HEIGHT;
        attr.pic_width = MAX_PIC_WIDTH;
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_vpc_create_chn_for_acl(&chn, &attr), hi_mpi_vpc_create_chn_for_acl);
        ACL_REQUIRES_OK(SetCscMatrixConfig(channelDesc, chn));
        return ACL_SUCCESS;
    }

    aclError CreateHimpiChannelDvppJpege(const acldvppChannelDesc *const channelDesc, hi_s32 &chn)
    {
        hi_venc_chn_attr jpegeAttr = {};
        GetJpegeConfig(channelDesc, jpegeAttr);
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_jpege_create_chn_for_acl(&chn, &jpegeAttr), hi_mpi_jpege_create_chn_for_acl);
        return ACL_SUCCESS;
    }

    aclError CreateHimpiChannelDvppJpegd(const acldvppChannelDesc *const channelDesc, hi_s32 &chn)
    {
        hi_vdec_chn_attr jpegdAttr = {};
        jpegdAttr.type = HI_PT_JPEG;
        jpegdAttr.mode = HI_VDEC_SEND_MODE_FRAME;
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_jpegd_create_chn_for_acl(&chn, &jpegdAttr), hi_mpi_jpegd_create_chn_for_acl);
        ACL_REQUIRES_OK(SetJpegdPrecisionModeConfig(channelDesc, chn));
        return ACL_SUCCESS;
    }
}

namespace acl {
    namespace dvpp {
    aclError ImageProcessorV300::acldvppSetResizeConfigInterpolation(acldvppResizeConfig *const resizeConfig,
                                                                     const uint32_t interpolation)
    {
        ACL_LOG_DEBUG("start to execute acldvppSetResizeConfigInterpolation.");
        ACL_REQUIRES_NOT_NULL(resizeConfig);
        // 0 self developed interpolation algorithm; 1 bilinear; 2 Nearest neighbor(opencv);
        // 3 Bilinear; 4 Nearest neighbor(tf) 5 YUV_SCALER
        if (interpolation > 5U) {
            ACL_LOG_ERROR("the current interpolation[%u] is not support, only supporte [0,5]", interpolation);
            const std::string valueStr = std::to_string(interpolation);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"interpolation", valueStr.c_str(), "only supporte [0,5]"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        resizeConfig->dvppResizeConfig.interpolation = interpolation;
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::CreateHimpiChannel(acldvppChannelDesc *const channelDesc,
        const acldvppChannelMode &mode)
    {
        hi_s32 ret = 0;
        hi_s32 chn = 0;
        if (mode == DVPP_CHNMODE_VPC) {
            ret = CreateHimpiChannelDvppVpc(channelDesc, chn);
        } else if (mode == DVPP_CHNMODE_JPEGE) {
            ret = CreateHimpiChannelDvppJpege(channelDesc, chn);
        } else if (mode == DVPP_CHNMODE_JPEGD) {
            ret = CreateHimpiChannelDvppJpegd(channelDesc, chn);
        } else {
            ACL_LOG_INFO("current mode is %d", mode);
        }
        if (ret != 0) {
            // need to destroy current success channel
            (void)acldvppDestroyChannel(channelDesc);
            ACL_LOG_CALL_ERROR("create channel %d fail", mode);
            return ret;
        }
        {
            const std::unique_lock<std::mutex> lk{channelDesc->mutexForHimpiChnMap};
            channelDesc->himpiChannelIdMap[mode] = chn;
        }
        ACL_LOG_INFO("crete %d channel %d success", mode, chn);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppCreateChannel(acldvppChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("start to execute acldvppCreateChannel");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_sys_init_for_acl(), hi_mpi_sys_init_for_acl);
        const uint32_t channelMode = channelDesc->dvppDesc.channelMode;
        const bool isVpcChannel =
            (((channelMode) & (static_cast<uint32_t>(DVPP_CHNMODE_VPC))) == DVPP_CHNMODE_VPC);
        ACL_LOG_INFO("current mode is %u", channelMode);
        if (isVpcChannel) {
            ACL_LOG_INFO("start to create vpc channel");
            ACL_REQUIRES_OK(CreateHimpiChannel(channelDesc, DVPP_CHNMODE_VPC));
        }
        const bool isJpegdChannel =
            (((channelMode) & (static_cast<uint32_t>(DVPP_CHNMODE_JPEGD))) == DVPP_CHNMODE_JPEGD);
        if (isJpegdChannel) {
            ACL_LOG_INFO("start to create jpegd channel");
            ACL_REQUIRES_OK(CreateHimpiChannel(channelDesc, DVPP_CHNMODE_JPEGD));
        }
        const bool isJpegeChannel =
            (((channelMode) & (static_cast<uint32_t>(DVPP_CHNMODE_JPEGE))) == DVPP_CHNMODE_JPEGE);
        if (isJpegeChannel) {
            ACL_LOG_INFO("start to create jpege channel");
            ACL_REQUIRES_OK(CreateHimpiChannel(channelDesc, DVPP_CHNMODE_JPEGE));
        }
        const bool isPngChannel =
            (((channelMode) & (static_cast<uint32_t>(DVPP_CHNMODE_PNGD))) == DVPP_CHNMODE_PNGD);
        if (isPngChannel) {
            ACL_LOG_INFO("start to create pngd channel");
            ACL_REQUIRES_OK(DvppImageCreateChannel(channelDesc));
        }
        ACL_LOG_INFO("execute acldvppCreateChannel successfully");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppDestroyChannel(acldvppChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("start to execute acldvppDestroyChannel");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        const uint32_t channelMode = channelDesc->dvppDesc.channelMode;
        const bool isPngChannel =
            (((channelMode) & (static_cast<uint32_t>(DVPP_CHNMODE_PNGD))) == DVPP_CHNMODE_PNGD);
        if (isPngChannel) {
            ACL_LOG_INFO("start to destroy pngd channel");
            ACL_REQUIRES_OK(DvppImageDestroyChannel(channelDesc));
        }
        const std::unique_lock<std::mutex> lk{channelDesc->mutexForHimpiChnMap};
        for (auto it = channelDesc->himpiChannelIdMap.cbegin(); it != channelDesc->himpiChannelIdMap.cend(); ++it) {
            ACL_LOG_INFO("start to destroy channel %d", it->first);
            const auto &itFunc = destroyChnMap.find(it->first);
            const int32_t chn = it->second;
            if (itFunc != destroyChnMap.end()) {
                if (itFunc->second(chn) != 0) {
                    ACL_LOG_CALL_ERROR("destroy channel failed, mode is %d", chn);
                }
            }
        }
        channelDesc->himpiChannelIdMap.clear();
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppJpegDecodeAsync(acldvppChannelDesc *const channelDesc,
                                                        const void *const data,
                                                        const uint32_t size,
                                                        acldvppPicDesc *const outputDesc,
                                                        const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppJpegDecodeAsync, size is %u", size);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_JPEGD, chn));
        hi_img_stream_enhance imgStream = {};
        imgStream.device_addr = const_cast<hi_u8 *>(reinterpret_cast<const hi_u8 *>(data));
        imgStream.device_data_len = size;
        imgStream.local_addr = nullptr;
        imgStream.local_data_len = 0U;
        imgStream.enType = HI_PT_JPEG;
        hi_pic_info outPic = {};
        ConvertUserPicDescToHimpiPicInfo(outputDesc->dvppPicDesc, outPic);
        ACL_LOG_INFO("start to call hi_mpi_jpegd_decode_for_acl, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_jpegd_decode_for_acl(chn, &imgStream, &outPic, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_jpegd_decode_for_acl fail, channel id is %d", chn);
            return ret;
        }
        RefreshHimpiPicInfoToUserPicDesc(outPic, outputDesc->dvppPicDesc);
        ACL_LOG_INFO("call hi_mpi_jpegd_decode_for_acl success, channel id is %d", chn);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppJpegEncodeAsync(acldvppChannelDesc *const channelDesc,
                                                        acldvppPicDesc *const inputDesc,
                                                        const void *const data,
                                                        uint32_t *const size,
                                                        acldvppJpegeConfig *const config,
                                                        const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppJpegEncodeAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(size);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(config);
        ACL_REQUIRES_POSITIVE(*size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_JPEGE, chn));
        hi_venc_jpeg_param param = {};
        param.qfactor = config->dvppJpegeConfig.level;
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_venc_set_jpeg_param_for_acl(chn, &param),
            hi_mpi_venc_set_jpeg_param_for_acl);
        hi_video_frame_info frame = {};
        FillVideoFrameInfo(inputDesc, frame);
        hi_img_stream jpegeStream = {};
        jpegeStream.type = HI_PT_JPEG;
        jpegeStream.addr = const_cast<hi_u8 *>(reinterpret_cast<const hi_u8 *>(data));
        jpegeStream.len = *size;
        hi_jpege_outsize_info imgOutsizeInfo = {};
        // jpege addr need 128N,so addr need use no offset addr
        void *devAddr = channelDesc->dataBuffer.data;
        if (aclRunMode_ == ACL_DEVICE) {
            devAddr = channelDesc->shareBuffer.data;
        }
        imgOutsizeInfo.jpege_size_addr = devAddr;
        imgOutsizeInfo.jpege_size_addr_len = static_cast<uint32_t>(sizeof(uint32_t));
        ACL_LOG_INFO("start to call hi_mpi_venc_send_jpege_frame_for_acl, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_venc_send_jpege_frame_for_acl(chn, &frame, &jpegeStream, &imgOutsizeInfo, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_venc_send_jpege_frame_for_acl fail, channel id is %d", chn);
            return ret;
        }
        if (aclRunMode_ == ACL_HOST) {
            ACL_REQUIRES_CALL_RTS_OK(rtMemcpyAsync(size, sizeof(uint32_t), devAddr,
                sizeof(uint32_t), RT_MEMCPY_DEVICE_TO_HOST, stream), rtMemcpyAsync);
        } else {
            ACL_REQUIRES_CALL_RTS_OK(rtMemcpyAsync(size, sizeof(uint32_t), devAddr,
                sizeof(uint32_t), RT_MEMCPY_DEVICE_TO_HOST_EX, stream), rtMemcpyAsync);
        }
        ACL_LOG_INFO("call hi_mpi_venc_send_jpege_frame success, channel id is %d", chn);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppJpegGetImageInfo(const void *const data,
                                                         const uint32_t size,
                                                         uint32_t *const width,
                                                         uint32_t *const height,
                                                         int32_t *const components,
                                                         acldvppJpegFormat *const format) const
    {
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(data);
        const bool noNeedGetImageInfo = (width == nullptr) && (height == nullptr) &&
                                  (components == nullptr) && (format == nullptr);
        if (noNeedGetImageInfo) {
            ACL_LOG_INFO("no need to get jpeg info");
            return ACL_SUCCESS;
        }
        hi_vdec_stream jpegStream = {};
        jpegStream.addr = const_cast<hi_u8 *>(reinterpret_cast<const hi_u8 *>(data));
        jpegStream.len = size;
        hi_img_info imgInfo = {};
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_dvpp_get_image_info_for_acl(HI_PT_JPEG, &jpegStream, &imgInfo, components),
            hi_mpi_dvpp_get_image_info_for_acl);
        if (width != nullptr) {
            *width = imgInfo.width;
        }
        if (height != nullptr) {
            *height = imgInfo.height;
        }
        if (format != nullptr) {
            ConvertJpegFormat(imgInfo.pixel_format, format);
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppJpegPredictEncSize(const acldvppPicDesc *const inputDesc,
                                                           const acldvppJpegeConfig *const config,
                                                           uint32_t *const size) const
    {
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(config);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(size);
        hi_video_frame_info frame = {};
        frame.v_frame.width = inputDesc->dvppPicDesc.width;
        frame.v_frame.height = inputDesc->dvppPicDesc.height;
        frame.v_frame.pixel_format = static_cast<hi_pixel_format>(inputDesc->dvppPicDesc.format);
        hi_venc_jpeg_param jpegParam = {};
        jpegParam.qfactor = config->dvppJpegeConfig.level;
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_venc_get_jpege_predicted_size_for_acl(&frame, &jpegParam, size),
            hi_mpi_venc_get_jpege_predicted_size_for_acl);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppJpegPredictDecSize(const void *const data,
                                                           const uint32_t dataSize,
                                                           const acldvppPixelFormat outputPixelFormat,
                                                           uint32_t *const decSize)
    {
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(decSize);
        hi_vdec_stream jpegStream = {};
        jpegStream.addr = const_cast<hi_u8 *>(reinterpret_cast<const hi_u8 *>(data));
        jpegStream.len = dataSize;
        hi_pic_info imgInfo = {};
        imgInfo.picture_format = static_cast<hi_pixel_format>(outputPixelFormat);
        ACL_REQUIRES_CALL_HIMPI_OK(hi_mpi_dvpp_get_pic_buf_size_for_acl(HI_PT_JPEG, &jpegStream, &imgInfo),
            hi_mpi_dvpp_get_image_info_for_acl);
        *decSize = imgInfo.picture_buffer_size;
        ACL_LOG_INFO("picture format %d predict jpegd size is %u", outputPixelFormat, *decSize);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcResizeAsync(acldvppChannelDesc *const channelDesc,
                                                       acldvppPicDesc *const inputDesc,
                                                       acldvppPicDesc *const outputDesc,
                                                       acldvppResizeConfig *const resizeConfig,
                                                       const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcResizeAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        hi_vpc_pic_info dstPic = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, dstPic);
        const hi_u32 interpolation = interpolationVec[resizeConfig->dvppResizeConfig.interpolation];
        ACL_LOG_INFO("start to call hi_mpi_vpc_resize_for_acl, channel id is %d, interpolation is %u",
            chn, interpolation);
        const hi_s32 ret = hi_mpi_vpc_resize_for_acl(chn, &srcPic, &dstPic, 0.0F, 0.0F, interpolation, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_resize_for_acl fail, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_resize_for_acl success, channel id is %d", chn);
        return ACL_SUCCESS;
    }

    static aclError ProcessCropResizePaste(const int32_t channelId,
        const acldvppPicDesc *const inputDesc,
        const acldvppPicDesc *const outputDesc,
        const acldvppRoiConfig *const cropArea,
        const acldvppResizeConfig *const resizeConfig,
        const acldvppRoiConfig *const pasteArea,
        const aclrtStream stream)
    {
        hi_vpc_pic_info srcPic = {};
        hi_vpc_crop_resize_paste_region cropResizePasteInfo = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, cropResizePasteInfo.dest_pic_info);
        if (cropArea != nullptr) {
            ACL_REQUIRES_OK(ConvertUserRoiCfgToHimpiCropInfo(cropArea, cropResizePasteInfo.crop_region));
        }
        ACL_REQUIRES_OK(ConvertUserResizeCfgToHimpiResizeInfo(outputDesc->dvppPicDesc,
            resizeConfig, cropResizePasteInfo.resize_info, nullptr, pasteArea));
        if (pasteArea != nullptr) {
            cropResizePasteInfo.dest_top_offset = pasteArea->dvppRoiConfig.upOffset;
            cropResizePasteInfo.dest_left_offset = pasteArea->dvppRoiConfig.leftOffset;
        }
        std::vector<hi_vpc_crop_resize_paste_region> cropResizePasteInfoVec;
        cropResizePasteInfoVec.emplace_back(cropResizePasteInfo);
        ACL_LOG_INFO("start to call hi_mpi_vpc_crop_resize_paste_for_acl interface, channel id is %d", channelId);
        const hi_s32 ret = hi_mpi_vpc_crop_resize_paste_for_acl(channelId, &srcPic,
            cropResizePasteInfoVec.data(), 1U, stream);
        if (ret != 0) {
            ACL_LOG_ERROR("call hi_mpi_vpc_crop_resize_paste_for_acl failed, channel id is %d", channelId);
            return ret;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcCropAsync(acldvppChannelDesc *const channelDesc,
                                                     acldvppPicDesc *const inputDesc,
                                                     acldvppPicDesc *const outputDesc,
                                                     acldvppRoiConfig *const cropArea,
                                                     const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropArea);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessCropResizePaste(chn, inputDesc, outputDesc, cropArea, nullptr, nullptr, stream);
    }

    aclError ImageProcessorV300::acldvppVpcCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                           acldvppPicDesc *const inputDesc,
                                                           acldvppPicDesc *const outputDesc,
                                                           acldvppRoiConfig *const cropArea,
                                                           acldvppResizeConfig *const resizeConfig,
                                                           const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizeAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropArea);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessCropResizePaste(chn, inputDesc, outputDesc, cropArea, resizeConfig, nullptr, stream);
    }

    aclError ImageProcessorV300::acldvppVpcCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                             acldvppPicDesc *const inputDesc,
                                                             acldvppPicDesc *const outputDesc,
                                                             acldvppRoiConfig *const cropArea,
                                                             acldvppRoiConfig *const pasteArea,
                                                             const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAndPasteAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropArea);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pasteArea);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessCropResizePaste(chn, inputDesc, outputDesc, cropArea, nullptr, pasteArea, stream);
    }

    aclError ImageProcessorV300::acldvppVpcCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                                acldvppPicDesc *const inputDesc,
                                                                acldvppPicDesc *const outputDesc,
                                                                acldvppRoiConfig *const cropArea,
                                                                acldvppRoiConfig *const pasteArea,
                                                                acldvppResizeConfig *const resizeConfig,
                                                                const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizePasteAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropArea);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pasteArea);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessCropResizePaste(chn, inputDesc, outputDesc, cropArea, resizeConfig, pasteArea, stream);
    }

    aclError ImageProcessorV300::acldvppVpcMakeBorderAsync(const acldvppChannelDesc *const channelDesc,
                                                           const acldvppPicDesc *const inputDesc,
                                                           acldvppPicDesc *const outputDesc,
                                                           const acldvppBorderConfig *const borderConfig,
                                                           const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcMakeBorderAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(borderConfig);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        hi_vpc_pic_info dstPic = {};
        hi_vpc_make_border_info makeBorderInfo = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, dstPic);
        ConvertUserBorderCfgToHimpiBorderInfo(borderConfig, makeBorderInfo);
        ACL_LOG_INFO("start to call hi_mpi_vpc_copy_make_border_for_acl interface, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_vpc_copy_make_border_for_acl(chn, &srcPic, &dstPic, makeBorderInfo, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_copy_make_border_for_acl failed, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_copy_make_border_for_acl success, channel id is %d", chn);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::ProcessBatchCropResizeBorder(const int32_t channelId,
        uint32_t *const roiNums, const uint32_t size, const acldvppBatchPicDesc *const srcBatchPicDescs,
        const acldvppBatchPicDesc *const dstBatchPicDescs, const acldvppRoiConfig *const cropAreas[],
        const acldvppResizeConfig *const resizeConfig, acldvppBorderConfig *borderCfgs[],
        const aclrtStream stream) const
    {
        std::vector<hi_vpc_pic_info> srcPicVec;
        std::vector<const hi_vpc_pic_info *> srcPicPtrVec;
        uint32_t totalRoiNums = 0U;
        ACL_REQUIRES_OK(CheckSrcBatchSize(srcBatchPicDescs, size));
        for (uint32_t i = 0U; i < size; ++i) {
            hi_vpc_pic_info srcPic = {};
            ConvertUserPicDescToHimpiVpcPicInfo(srcBatchPicDescs->aclDvppPicDescs[i].dvppPicDesc, true, srcPic);
            srcPicVec.emplace_back(srcPic);
            totalRoiNums += roiNums[i];
        }
        for (size_t k = 0U; k < srcPicVec.size(); ++k) {
            srcPicPtrVec.emplace_back(&srcPicVec[k]);
        }
        ACL_REQUIRES_OK(CheckDstBatchSize(dstBatchPicDescs, totalRoiNums));
        std::vector<hi_vpc_crop_resize_border_region> cropResizeBorderInfoVec;
        for (uint32_t j = 0U; j < totalRoiNums; ++j) {
            hi_vpc_crop_resize_border_region cropResizeBorderInfo = {};
            ConvertUserPicDescToHimpiVpcPicInfo(dstBatchPicDescs->aclDvppPicDescs[j].dvppPicDesc, false,
                cropResizeBorderInfo.dest_pic_info);
            if (cropAreas != nullptr) {
                ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas[j]);
                ACL_REQUIRES_OK(ConvertUserRoiCfgToHimpiCropInfo(cropAreas[j], cropResizeBorderInfo.crop_region));
            }
            const bool isSetBorder = ((borderCfgs != nullptr) && (borderCfgs[j] != nullptr));
            const acldvppBorderConfig *bordCfg = isSetBorder ? borderCfgs[j] : nullptr;
            ACL_REQUIRES_OK(ConvertUserResizeCfgToHimpiResizeInfo(dstBatchPicDescs->aclDvppPicDescs[j].dvppPicDesc,
                resizeConfig, cropResizeBorderInfo.resize_info, bordCfg, nullptr));
            if (borderCfgs != nullptr) {
                ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(borderCfgs[j]);
                cropResizeBorderInfo.dest_top_offset = borderCfgs[j]->dvppBorderConfig.top;
                cropResizeBorderInfo.dest_left_offset = borderCfgs[j]->dvppBorderConfig.left;
                cropResizeBorderInfo.border_type =
                    static_cast<hi_vpc_bord_type>(borderCfgs[j]->dvppBorderConfig.borderType);
                for (uint32_t k = 0U; k < DVPP_MAKE_BORDER_MAX_COMPONENT; ++k) {
                    cropResizeBorderInfo.scalar_value.val[k] = borderCfgs[j]->dvppBorderConfig.value[k];
                }
            }
            cropResizeBorderInfoVec.emplace_back(cropResizeBorderInfo);
        }
        ACL_LOG_INFO("start to call hi_mpi_vpc_batch_crop_resize_make_border_for_acl interface,"
            "channel id is %d, total dst size is %u", channelId, totalRoiNums);
        const hi_s32 ret = hi_mpi_vpc_batch_crop_resize_make_border_for_acl(channelId, srcPicPtrVec.data(),
            size, cropResizeBorderInfoVec.data(), roiNums, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_batch_crop_resize_make_border_for_acl failed,"
                " channel id is %d", channelId);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_batch_crop_resize_make_border_for_acl success, channel id is %d", channelId);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *const channelDesc,
                                                                          acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                          uint32_t *const roiNums,
                                                                          const uint32_t size,
                                                                          acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                          acldvppRoiConfig *cropAreas[],
                                                                          acldvppBorderConfig *borderCfgs[],
                                                                          acldvppResizeConfig *const resizeConfig,
                                                                          const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizeMakeBorderAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(borderCfgs);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessBatchCropResizeBorder(chn, roiNums, size, srcBatchPicDescs, dstBatchPicDescs,
            cropAreas, resizeConfig, borderCfgs, stream);
    }

    aclError ImageProcessorV300::ProcessBatchCropResizePaste(const int32_t channelId,
        uint32_t *const roiNums,
        const uint32_t size,
        const acldvppBatchPicDesc *const srcBatchPicDescs,
        const acldvppBatchPicDesc *const dstBatchPicDescs,
        const acldvppRoiConfig *const cropAreas[],
        const acldvppResizeConfig *const resizeConfig,
        acldvppRoiConfig *pasteAreas[],
        const aclrtStream stream) const
    {
        std::vector<hi_vpc_pic_info> srcPicVec;
        std::vector<const hi_vpc_pic_info *> srcPicPtrVec;
        uint32_t totalRoiNums = 0U;
        ACL_REQUIRES_OK(CheckSrcBatchSize(srcBatchPicDescs, size));
        for (uint32_t i = 0U; i < size; ++i) {
            hi_vpc_pic_info srcPic = {};
            ConvertUserPicDescToHimpiVpcPicInfo(srcBatchPicDescs->aclDvppPicDescs[i].dvppPicDesc, true, srcPic);
            srcPicVec.emplace_back(srcPic);
            totalRoiNums += roiNums[i];
        }
        for (size_t k = 0U; k < srcPicVec.size(); ++k) {
            srcPicPtrVec.emplace_back(&srcPicVec[k]);
        }
        ACL_REQUIRES_OK(CheckDstBatchSize(dstBatchPicDescs, totalRoiNums));
        std::vector<hi_vpc_crop_resize_paste_region> cropResizePasteInfoVec;
        for (uint32_t j = 0U; j < totalRoiNums; ++j) {
            hi_vpc_crop_resize_paste_region cropResizePasteInfo = {};
            ConvertUserPicDescToHimpiVpcPicInfo(dstBatchPicDescs->aclDvppPicDescs[j].dvppPicDesc, false,
                cropResizePasteInfo.dest_pic_info);
            if (cropAreas != nullptr) {
                ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas[j]);
                ACL_REQUIRES_OK(ConvertUserRoiCfgToHimpiCropInfo(cropAreas[j], cropResizePasteInfo.crop_region));
            }
            const bool isSetPaste = ((pasteAreas != nullptr) && (pasteAreas[j] != nullptr));
            acldvppRoiConfig * const pasteCfg = isSetPaste ? pasteAreas[j] : nullptr;
            ACL_REQUIRES_OK(ConvertUserResizeCfgToHimpiResizeInfo(dstBatchPicDescs->aclDvppPicDescs[j].dvppPicDesc,
                resizeConfig, cropResizePasteInfo.resize_info, nullptr, pasteCfg));
            if (pasteAreas != nullptr) {
                ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pasteAreas[j]);
                cropResizePasteInfo.dest_top_offset = pasteAreas[j]->dvppRoiConfig.upOffset;
                cropResizePasteInfo.dest_left_offset = pasteAreas[j]->dvppRoiConfig.leftOffset;
            }
            cropResizePasteInfoVec.emplace_back(cropResizePasteInfo);
        }
        ACL_LOG_INFO("start to call hi_mpi_vpc_batch_crop_resize_paste_for_acl interface, channel id is %d,"
            " total dst size is %u", channelId, totalRoiNums);
        const hi_s32 ret = hi_mpi_vpc_batch_crop_resize_paste_for_acl(channelId, srcPicPtrVec.data(),
            size, cropResizePasteInfoVec.data(), roiNums, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_batch_crop_resize_paste_for_acl failed, channel id is %d", channelId);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_batch_crop_resize_paste_for_acl success, channel id is %d", channelId);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcBatchCropAsync(acldvppChannelDesc *const channelDesc,
                                                          acldvppBatchPicDesc *const srcBatchPicDescs,
                                                          uint32_t *const roiNums,
                                                          const uint32_t size,
                                                          acldvppBatchPicDesc *const dstBatchPicDescs,
                                                          acldvppRoiConfig *cropAreas[],
                                                          const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessBatchCropResizePaste(chn, roiNums, size, srcBatchPicDescs, dstBatchPicDescs,
            cropAreas, nullptr, nullptr, stream);
    }

    aclError ImageProcessorV300::acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                                acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                uint32_t *const roiNums,
                                                                const uint32_t size,
                                                                acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                acldvppRoiConfig *cropAreas[],
                                                                acldvppResizeConfig *const resizeConfig,
                                                                const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizeAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessBatchCropResizePaste(chn, roiNums, size, srcBatchPicDescs, dstBatchPicDescs,
            cropAreas, resizeConfig, nullptr, stream);
    }


    aclError ImageProcessorV300::acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                                  acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                  uint32_t *const roiNums,
                                                                  const uint32_t size,
                                                                  acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                  acldvppRoiConfig *cropAreas[],
                                                                  acldvppRoiConfig *pasteAreas[],
                                                                  const aclrtStream stream)
    {
        // validate parametes
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAndPasteAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pasteAreas);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessBatchCropResizePaste(chn, roiNums, size, srcBatchPicDescs, dstBatchPicDescs,
            cropAreas, nullptr, pasteAreas, stream);
    }

    aclError ImageProcessorV300::acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                                     acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                     uint32_t *const roiNums,
                                                                     const uint32_t size,
                                                                     acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                     acldvppRoiConfig *cropAreas[],
                                                                     acldvppRoiConfig *pasteAreas[],
                                                                     acldvppResizeConfig *const resizeConfig,
                                                                     const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizePasteAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pasteAreas);
        ACL_REQUIRES_POSITIVE(size);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        return ProcessBatchCropResizePaste(chn, roiNums, size, srcBatchPicDescs, dstBatchPicDescs,
            cropAreas, resizeConfig, pasteAreas, stream);
    }

    aclError ImageProcessorV300::acldvppVpcConvertColorAsync(acldvppChannelDesc *const channelDesc,
                                                             acldvppPicDesc *const inputDesc,
                                                             acldvppPicDesc *const outputDesc,
                                                             const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcConvertColorAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        hi_vpc_pic_info dstPic = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, dstPic);
        ACL_LOG_INFO("start to call hi_mpi_vpc_convert_color_for_acl, channel id is %d", chn);
        hi_csc_conf cscCfg = {};
        const hi_s32 ret = hi_mpi_vpc_convert_color_for_acl(chn, &srcPic, &dstPic, &cscCfg, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_convert_color_for_acl fail, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_convert_color_for_acl success, channel id is %d", chn);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcPyrDownAsync(acldvppChannelDesc *const channelDesc,
                                                        acldvppPicDesc *const inputDesc,
                                                        acldvppPicDesc *const outputDesc,
                                                        void *const reserve,
                                                        const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcPyrDownAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        if (reserve != nullptr) {
            ACL_LOG_ERROR("[Check][Reserve]paramete reserve must be null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"reserve"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        hi_vpc_pic_info dstPic = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, dstPic);
        // default param
        const uint32_t filterLevel = DEFAULT_FILTER_LEVEL;
        const uint16_t divisor = DEFAULT_DIVISOR;
        const hi_vpc_make_border_info makeBorderInfo = {2U, 2U, 2U, 2U, HI_BORDER_CONSTANT, {}};
        static int8_t gaussianFilter[5][5] = {{1, 4, 6, 4, 1},
                                              {4, 16, 24, 16, 4},
                                              {6, 24, 36, 24, 6},
                                              {4, 16, 24, 16, 4},
                                              {1, 4, 6, 4, 1}};
        ACL_LOG_INFO("start to call hi_mpi_vpc_pyrdown_for_acl, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_vpc_pyrdown_for_acl(chn, &srcPic, &dstPic, filterLevel, gaussianFilter,
            divisor, makeBorderInfo, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_pyrdown_for_acl fail, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("end to execute acldvppVpcPyrDownAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *const channelDesc,
                                                             const acldvppPicDesc *const inputDesc,
                                                             acldvppPicDesc *const outputDesc,
                                                             const acldvppLutMap *const lutMap,
                                                             const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcEqualizeHistAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(inputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(outputDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(lutMap);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(lutMap->dvppLutMap.map);
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        hi_vpc_pic_info dstPic = {};
        ConvertUserPicDescToHimpiVpcPicInfo(inputDesc->dvppPicDesc, true, srcPic);
        ConvertUserPicDescToHimpiVpcPicInfo(outputDesc->dvppPicDesc, false, dstPic);
        hi_vpc_lut_remap lutCfg = {};
        for (uint32_t i = 0U; i < LUT_MAP_DEFAULT_VALUE; ++i) {
            lutCfg.map_value_y_or_r[i] = lutMap->dvppLutMap.map[i];
            lutCfg.map_value_u_or_g[i] = lutMap->dvppLutMap.map[LUT_MAP_DEFAULT_VALUE + i];
            lutCfg.map_value_v_or_b[i] = lutMap->dvppLutMap.map[LUT_MAP_DEFAULT_VALUE + LUT_MAP_DEFAULT_VALUE + i];
        }
        ACL_LOG_INFO("start to call hi_mpi_vpc_equalize_hist_for_acl, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_vpc_equalize_hist_for_acl(chn, &srcPic, &dstPic, &lutCfg, stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_equalize_hist_for_acl fail, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("end to execute acldvppVpcEqualizeHistAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV300::acldvppVpcCalcHistAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const srcPicDesc,
                                                         acldvppHist *const hist,
                                                         void *const reserve,
                                                         const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcCalcHistAsync");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcPicDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(hist);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(hist->dvppHistDesc.hist);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(hist->shareBuffer.data);
        if (reserve != nullptr) {
            ACL_LOG_INNER_ERROR("[Check][Reserve]reserve param must be null, but addr = %p.", reserve);
            return ACL_ERROR_INVALID_PARAM;
        }
        int32_t chn = 0;
        ACL_REQUIRES_OK(GetHimpiChannel(channelDesc, DVPP_CHNMODE_VPC, chn));
        hi_vpc_pic_info srcPic = {};
        ConvertUserPicDescToHimpiVpcPicInfo(srcPicDesc->dvppPicDesc, false, srcPic);
        ACL_LOG_INFO("start to call hi_mpi_vpc_calc_hist_for_acl, channel id is %d", chn);
        const hi_s32 ret = hi_mpi_vpc_calc_hist_for_acl(chn, &srcPic, hist->shareBuffer.data,
            static_cast<uint32_t>(hist->shareBuffer.length), stream);
        if (ret != 0) {
            ACL_LOG_CALL_ERROR("call hi_mpi_vpc_calc_hist_for_acl fail, channel id is %d", chn);
            return ret;
        }
        ACL_LOG_INFO("call hi_mpi_vpc_calc_hist_for_acl success, channel id is %d", chn);
        if (aclRunMode_ == ACL_HOST) {
            ACL_REQUIRES_CALL_RTS_OK(rtMemcpyAsync(hist->dvppHistDesc.hist, hist->shareBuffer.length,
                hist->shareBuffer.data, hist->shareBuffer.length, RT_MEMCPY_DEVICE_TO_HOST, stream), rtMemcpyAsync);
        }
        ACL_LOG_INFO("end to execute acldvppVpcCalcHistAsync");
        return ACL_SUCCESS;
    }
    }
}
